<template>
  <view class="device-container">
    <view class="header">
      <text class="title">蓝牙设备管理</text>
    </view>
    
    <!-- 蓝牙状态 -->
    <view class="bluetooth-status">
      <text class="status-text">蓝牙状态：{{bluetoothStatus}}</text>
      <button v-if="!isBluetoothEnabled" @click="openBluetoothSettings" class="enable-btn">开启蓝牙</button>
    </view>

    <!-- 设备列表 -->
    <view class="device-list" v-if="isBluetoothEnabled">
      <view class="list-header">
        <text>可用设备</text>
        <button @click="startBluetoothDevicesDiscovery" class="scan-btn">扫描设备</button>
      </view>
      
      <view v-if="devices.length === 0" class="no-devices">
        <text>暂无设备，请点击扫描</text>
      </view>
      
      <view v-else class="device-items">
        <view v-for="(device, index) in devices" 
              :key="index" 
              class="device-item"
              @click="connectDevice(device)">
          <text class="device-name">{{device.name || '未知设备'}}</text>
          <text class="device-id">ID: {{device.deviceId}}</text>
          <text class="device-rssi">信号强度: {{device.RSSI}}dBm</text>
        </view>
      </view>
    </view>

    <!-- 已连接设备 -->
    <view class="connected-device" v-if="connectedDevice">
      <text class="section-title">已连接设备</text>
      <view class="device-info">
        <text>设备名称：{{connectedDevice.name || '未知设备'}}</text>
        <text>设备ID：{{connectedDevice.deviceId}}</text>
        <button @click="disconnectDevice" class="disconnect-btn">断开连接</button>
      </view>
    </view>

    <view v-if="pcmBlobUrl">
      <audio :src="pcmBlobUrl" controls></audio>
    </view>
    <view>{{ adpcmStatus }}</view>

    <!-- 新增WebSocket状态和结果显示 -->
    <view class="websocket-status">
      <view class="status-info">
        <text class="status-text">WebSocket状态：{{wsStatus}}</text>
        <text v-if="wsStatus === '已连接'" class="status-connected">●</text>
        <text v-else-if="wsStatus === '正在连接...'" class="status-connecting">●</text>
        <text v-else class="status-disconnected">●</text>
      </view>
      <view class="status-buttons">
        <button v-if="!isWsConnected" @click="initWebSocket" class="connect-btn">连接WebSocket</button>
        <button v-else @click="closeWebSocket" class="disconnect-btn">断开WebSocket</button>
      </view>
    </view>
    
    <view v-if="wsResult" class="websocket-result">
      <text class="result-title">识别结果：</text>
      <text class="result-content">{{wsResult}}</text>
    </view>

    <!-- 添加测试按钮 -->
    <button @click="testAudioData" class="test-btn">测试音频数据</button>
  </view>
</template>

<script>
import { imaAdpcmDecode } from '@/utils/ima-adpcm.js';
import { pcmToWav } from '@/utils/adpcm-frame.js';
import AdpcmFrameDecoder from '@/utils/adpcm-frame.js';

export default {
  data() {
    return {
      bluetoothStatus: '未开启',
      isBluetoothEnabled: false,
      devices: [],
      connectedDevice: null,
      isScanning: false,
      services: {
        fff0: {
          uuid: '0000FFF0-0000-1000-8000-00805F9B34FB',
          characteristics: {
            notify: '0000FFF4-0000-1000-8000-00805F9B34FB',
            write: '0000FFF2-0000-1000-8000-00805F9B34FB'
          }
        },
        fff1: {
          uuid: '0000FFF1-0000-1000-8000-00805F9B34FB',
          characteristics: {
            notify: '0000FFF1-0000-1000-8000-00805F9B34FB'
          }
        },
        d0ff: {
          uuid: '0000D0FF-0000-1000-8000-00805F9B34FB',
          characteristics: {
            notify: '0000D002-0000-1000-8000-00805F9B34FB',
            write: '0000D001-0000-1000-8000-00805F9B34FB'
          }
        }
      },
      receivedData: [],
      adpcmDecoder: null,
      adpcmStatus: '',
      pcmBlobUrl: '',
      // 修改WebSocket相关变量
      socketTask: null,
      wsStatus: '未连接',
      wsResult: '',
      isWsConnected: false,
      wsRetryCount: 0,
      maxRetries: 3,
      wsRetryTimer: null,
      wsUrl: 'ws://qixin.yeshan.fun/ws/speech_v2',
      // 新增WebSocket配置
      wsConfig: {
        header: {
          'Origin': 'http://qixin.yeshan.fun',
          'User-Agent': 'Mozilla/5.0',
          'Accept': '*/*',
          'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
          'Cache-Control': 'no-cache',
          'Pragma': 'no-cache'
        },
        protocols: ['speech-protocol-v2'],
        timeout: 10000
      },
      // 新增心跳相关配置
      heartbeatConfig: {
        interval: 30000, // 心跳间隔30秒
        timeout: 5000,   // 心跳超时时间
        lastHeartbeatTime: 0, // 上次心跳时间
        isHeartbeatEnabled: false, // 心跳开关
        isSendingAudio: false // 是否正在发送音频数据
      },
      // 新增数据队列管理
      dataQueueManager: {
        queue: [],
        isProcessing: false,
        lastProcessTime: 0,
        processInterval: 40, // 修改处理间隔为40ms
        minSendSize: 1,
        maxQueueSize: 1000
      },
      // 新增WebSocket状态管理
      wsState: {
        isManualClose: false,
        isAppHide: false,
        reconnectTimer: null,
        reconnectCount: 0,
        maxReconnectCount: 5,
        reconnectInterval: 2000
      },
      // 修改音频数据缓冲区配置
      audioBuffer: {
        data: new Uint8Array(0),
        isStartFrameSent: false,
        isEndFrameSent: false,
        minChunkSize: 1280, // 最小发送块大小
        maxBufferSize: 12800, // 最大缓冲区大小
        minStartFrameSize: 8000, // 起始帧最小数据量
        frameSize: 8000, // 标准帧大小
        lastSendTime: 0, // 上次发送时间
        sendInterval: 40 // 发送间隔(ms)
      },
      // 修改识别结果累积数组
      recognitionResults: [],
      // 添加结果合并定时器
      resultMergeTimer: null,
      // 修改结果合并配置
      resultMergeConfig: {
        interval: 500, // 合并间隔（毫秒）
        maxWaitTime: 2000, // 最大等待时间（毫秒）
        isEndFrameReceived: false, // 是否收到结束帧
        lastMergeTime: 0 // 上次合并时间
      }
    }
  },
  
  onLoad() {
    this.checkBluetoothStatus();
    // 初始化ADPCM解码器
    this.adpcmDecoder = new AdpcmFrameDecoder(8000);
    // 只设置一次全局监听，只处理FFF0服务下F1特征值
    uni.onBLECharacteristicValueChange((res) => {
      const value = this.arrayBufferToHex(res.value);
      if (
        res.serviceId && res.serviceId.toUpperCase() === this.services.fff0.uuid.toUpperCase() &&
        res.characteristicId && res.characteristicId.toUpperCase().endsWith('F1-0000-1000-8000-00805F9B34FB')
      ) {
        this.handleBluetoothData({ value });
      }
    });

    // 初始化WebSocket连接
    this.initWebSocket();
  },
  
  onShow() {
    this.checkBluetoothStatus();
    // 如果App从后台恢复，重置状态并尝试重连
    if (this.wsState.isAppHide) {
      this.wsState.isAppHide = false;
      if (!this.isWsConnected) {
        this.initWebSocket();
      }
    }
  },
  
  onHide() {
    this.stopNotifyCheck();
    // 标记App进入后台
    this.wsState.isAppHide = true;
    // 暂停心跳检测
    this.clearWebSocketTimers();
  },
  
  onUnload() {
    this.stopNotifyCheck();
    // 页面卸载时才关闭WebSocket连接
    this.closeWebSocket();
    // 移除WebSocket事件监听
    uni.offSocketOpen();
    uni.offSocketMessage();
    uni.offSocketClose();
    uni.offSocketError();
  },
  
  methods: {
    // 检查蓝牙状态
    checkBluetoothStatus() {
      // 直接尝试初始化蓝牙适配器
      uni.openBluetoothAdapter({
        success: (res) => {
          console.log('蓝牙初始化成功');
          this.isBluetoothEnabled = true;
          this.bluetoothStatus = '已开启';
          this.checkConnectedDevices();
        },
        fail: (err) => {
          console.error('蓝牙初始化失败', err);
          this.isBluetoothEnabled = false;
          this.bluetoothStatus = '未开启';
          this.devices = [];
          this.connectedDevice = null;
          
          // 根据错误码显示不同提示
          let errorMsg = '蓝牙初始化失败';
          if (err.code === 10001) {
            errorMsg = '请开启蓝牙功能';
          } else if (err.code === 10002) {
            errorMsg = '没有找到蓝牙设备';
          } else if (err.code === 10003) {
            errorMsg = '蓝牙连接失败';
          } else if (err.code === 10004) {
            errorMsg = '没有找到指定服务';
          } else if (err.code === 10005) {
            errorMsg = '没有找到指定特征值';
          } else if (err.code === 10006) {
            errorMsg = '当前连接已断开';
          } else if (err.code === 10007) {
            errorMsg = '当前特征值不支持此操作';
          } else if (err.code === 10008) {
            errorMsg = '其余所有系统上报的异常';
          } else if (err.code === 10009) {
            errorMsg = 'Android 系统特有，系统版本低于 4.3 不支持 BLE';
          } else if (err.code === 10012) {
            errorMsg = '连接超时';
          } else if (err.code === 10013) {
            errorMsg = '连接 deviceId 为空或者是格式不正确';
          }
          
          uni.showModal({
            title: '提示',
            content: errorMsg,
            confirmText: '去设置',
            success: (res) => {
              if (res.confirm) {
                this.openBluetoothSettings();
              }
            }
          });
        }
      });
    },
    
    // 打开系统蓝牙设置
    openBluetoothSettings() {
      // #ifdef APP-PLUS
      if (plus.os.name.toLowerCase() === 'android') {
        const main = plus.android.runtimeMainActivity();
        const Intent = plus.android.importClass('android.content.Intent');
        const Settings = plus.android.importClass('android.provider.Settings');
        const intent = new Intent(Settings.ACTION_BLUETOOTH_SETTINGS);
        main.startActivity(intent);
      } else if (plus.os.name.toLowerCase() === 'ios') {
        const UIApplication = plus.ios.importClass('UIApplication');
        const NSURL = plus.ios.importClass('NSURL');
        const url = NSURL.URLWithString('App-Prefs:root=Bluetooth');
        UIApplication.sharedApplication().openURL(url);
      }
      // #endif
      
      // #ifdef H5
      uni.showToast({
        title: '请在系统设置中开启蓝牙',
        icon: 'none'
      });
      // #endif
    },
    
    // 开始扫描设备
    startBluetoothDevicesDiscovery() {
      if (this.isScanning) return
      
      this.isScanning = true
      this.devices = []
      
      uni.startBluetoothDevicesDiscovery({
        success: (res) => {
          console.log('开始扫描设备')
          // 监听发现新设备事件
          uni.onBluetoothDeviceFound((res) => {
            const newDevices = res.devices
            newDevices.forEach(device => {
              // 过滤掉没有名称的设备
              if (device.name) {
                const existDevice = this.devices.find(d => d.deviceId === device.deviceId)
                if (!existDevice) {
                  this.devices.push(device)
                }
              }
            })
          })
          
          // 10秒后停止扫描
          setTimeout(() => {
            this.stopBluetoothDevicesDiscovery()
          }, 10000)
        },
        fail: (err) => {
          console.error('扫描设备失败', err)
          this.isScanning = false
          uni.showToast({
            title: '扫描设备失败',
            icon: 'none'
          })
        }
      })
    },
    
    // 停止扫描设备
    stopBluetoothDevicesDiscovery() {
      uni.stopBluetoothDevicesDiscovery({
        success: (res) => {
          console.log('停止扫描设备')
          this.isScanning = false
        }
      })
    },
    
    // 连接设备
    connectDevice(device) {
      uni.showLoading({
        title: '正在连接...'
      });
      
      // 先停止扫描
      this.stopBluetoothDevicesDiscovery();
      
      uni.createBLEConnection({
        deviceId: device.deviceId,
        timeout: 10000, // 设置超时时间为10秒
        success: (res) => {
          console.log('连接设备成功', device);
          this.connectedDevice = device;
          uni.showToast({
            title: '连接成功',
            icon: 'success'
          });
          
          // 延迟1秒后获取服务，确保连接稳定
          setTimeout(() => {
            this.getBLEDeviceServices(device.deviceId);
          }, 1000);
        },
        fail: (err) => {
          console.error('连接设备失败', err);
          uni.showToast({
            title: '连接失败',
            icon: 'none'
          });
        },
        complete: () => {
          uni.hideLoading();
        }
      });
    },
    
    // 断开设备连接
    disconnectDevice() {
      if (!this.connectedDevice) return
      
      uni.closeBLEConnection({
        deviceId: this.connectedDevice.deviceId,
        success: (res) => {
          console.log('断开连接成功')
          this.connectedDevice = null
          uni.showToast({
            title: '已断开连接',
            icon: 'success'
          })
        },
        fail: (err) => {
          console.error('断开连接失败', err)
        }
      })
    },
    
    // 获取设备的服务
    getBLEDeviceServices(deviceId) {
      console.log('开始获取服务，设备ID：', deviceId);
      
      // 确保设备已连接
      uni.getConnectedBluetoothDevices({
        success: (res) => {
          const connectedDevices = res.devices || [];
          const isConnected = connectedDevices.some(device => device.deviceId === deviceId);
          
          if (!isConnected) {
            console.error('设备未连接，无法获取服务');
            uni.showToast({
              title: '设备未连接',
              icon: 'none'
            });
            return;
          }
          
          console.log('设备已连接，开始获取服务列表');
          
          // 获取服务
          uni.getBLEDeviceServices({
            deviceId,
            success: (res) => {
              console.log('获取服务成功，设备ID：', deviceId);
              console.log('服务列表：', JSON.stringify(res.services, null, 2));
              
              if (!res.services || res.services.length === 0) {
                console.log('未发现服务，尝试重新获取...');
                // 延迟2秒后重试
                setTimeout(() => {
                  this.getBLEDeviceServices(deviceId);
                }, 2000);
                return;
              }
              
              // 遍历所有服务
              res.services.forEach(service => {
                console.log('发现服务：', {
                  uuid: service.uuid,
                  isPrimary: service.isPrimary
                });
                // 获取每个服务的特征值
                this.getBLEDeviceCharacteristics(deviceId, service.uuid);
              });
            },
            fail: (err) => {
              console.error('获取服务失败：', {
                error: err,
                deviceId: deviceId
              });
              // 延迟2秒后重试
              setTimeout(() => {
                this.getBLEDeviceServices(deviceId);
              }, 2000);
            }
          });
        },
        fail: (err) => {
          console.error('检查设备连接状态失败：', err);
        }
      });
    },
    
    // 获取特征值
    getBLEDeviceCharacteristics(deviceId, serviceId) {
      console.log('开始获取特征值：', {
        deviceId: deviceId,
        serviceId: serviceId
      });
      
      uni.getBLEDeviceCharacteristics({
        deviceId,
        serviceId,
        success: (res) => {
          console.log('获取特征值成功：', {
            deviceId: deviceId,
            serviceId: serviceId
          });
          console.log('特征值列表：', JSON.stringify(res.characteristics, null, 2));
          
          if (!res.characteristics || res.characteristics.length === 0) {
            console.log('未发现特征值，服务UUID：', serviceId);
            return;
          }
          
          // 只对F1结尾的特征值启用notify
          res.characteristics.forEach(characteristic => {
            if (
              characteristic.properties.notify &&
              characteristic.uuid.toUpperCase().endsWith('F1-0000-1000-8000-00805F9B34FB')
            ) {
              console.log('对FFF0服务下F1特征值启用notify：', characteristic.uuid);
              setTimeout(() => {
                this.enableNotify(deviceId, serviceId, characteristic.uuid);
              }, 1000);
            } else {
              console.log('跳过非F1或不支持notify的特征值：', characteristic.uuid);
            }
          });
        },
        fail: (err) => {
          console.error('获取特征值失败：', {
            error: err,
            deviceId: deviceId,
            serviceId: serviceId
          });
        }
      });
    },
    
    // 启用通知
    enableNotify(deviceId, serviceId, characteristicId) {
      console.log('准备启用通知：', {
        deviceId,
        serviceId,
        characteristicId
      });
      uni.notifyBLECharacteristicValueChange({
        deviceId,
        serviceId,
        characteristicId,
        state: true,
        success: (res) => {
          console.log('启用通知成功：', {
            deviceId,
            serviceId,
            characteristicId
          });
        },
        fail: (err) => {
          console.error('启用通知失败：', {
            error: err,
            deviceId,
            serviceId,
            characteristicId
          });
        }
      });
    },
    
    // 读取特征值
    readBLECharacteristicValue(deviceId, serviceId, characteristicId) {
      console.log('准备读取特征值：', {
        deviceId,
        serviceId,
        characteristicId
      });
      
      uni.readBLECharacteristicValue({
        deviceId,
        serviceId,
        characteristicId,
        success: (res) => {
          console.log('读取特征值成功：', {
            deviceId,
            serviceId,
            characteristicId
          });
        },
        fail: (err) => {
          console.error('读取特征值失败：', {
            error: err,
            deviceId,
            serviceId,
            characteristicId
          });
        }
      });
    },
    
    // 写入特征值
    writeBLECharacteristicValue(deviceId, serviceId, characteristicId, value) {
      console.log('准备写入特征值：', {
        deviceId,
        serviceId,
        characteristicId,
        value: this.arrayBufferToHex(value)
      });
      
      uni.writeBLECharacteristicValue({
        deviceId,
        serviceId,
        characteristicId,
        value,
        success: (res) => {
          console.log('写入特征值成功：', {
            deviceId,
            serviceId,
            characteristicId,
            value: this.arrayBufferToHex(value)
          });
        },
        fail: (err) => {
          console.error('写入特征值失败：', {
            error: err,
            deviceId,
            serviceId,
            characteristicId,
            value: this.arrayBufferToHex(value)
          });
        }
      });
    },
    
    // ArrayBuffer 转 16 进制字符串
    arrayBufferToHex(buffer) {
      return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
    },
    
    // 检查已连接的设备
    checkConnectedDevices() {
      uni.getConnectedBluetoothDevices({
        success: (res) => {
          if (res.devices && res.devices.length > 0) {
            this.connectedDevice = res.devices[0]
            console.log('已连接设备', this.connectedDevice)
          }
        }
      })
    },
    
    // 发送数据
    sendData(data) {
      console.log('准备发送数据：', data);
      
      if (!this.connectedDevice) {
        console.error('设备未连接，无法发送数据');
        uni.showToast({
          title: '设备未连接',
          icon: 'none'
        });
        return;
      }
      
      // 将数据转换为 ArrayBuffer
      const buffer = new ArrayBuffer(data.length);
      const dataView = new DataView(buffer);
      for (let i = 0; i < data.length; i++) {
        dataView.setUint8(i, data.charCodeAt(i));
      }
      
      console.log('数据已转换为 ArrayBuffer：', this.arrayBufferToHex(buffer));
      
      // 发送到 FFF0 服务
      uni.writeBLECharacteristicValue({
        deviceId: this.connectedDevice.deviceId,
        serviceId: this.services.fff0.uuid,
        characteristicId: this.services.fff0.characteristics.write,
        value: buffer,
        success: (res) => {
          console.log('发送数据成功：', {
            deviceId: this.connectedDevice.deviceId,
            serviceId: this.services.fff0.uuid,
            characteristicId: this.services.fff0.characteristics.write,
            data: this.arrayBufferToHex(buffer)
          });
        },
        fail: (err) => {
          console.error('发送数据失败：', {
            error: err,
            deviceId: this.connectedDevice.deviceId,
            serviceId: this.services.fff0.uuid,
            characteristicId: this.services.fff0.characteristics.write
          });
          uni.showToast({
            title: '发送失败',
            icon: 'none'
          });
        }
      });
    },
    
    // 启动通知检查
    startNotifyCheck() {
      // 清除可能存在的旧定时器
      this.stopNotifyCheck();
      
      // 每5秒检查一次通知状态
      this.checkInterval = setInterval(() => {
        this.checkNotifyStatus();
      }, 5000);
    },
    
    // 停止通知检查
    stopNotifyCheck() {
      if (this.checkInterval) {
        clearInterval(this.checkInterval);
        this.checkInterval = null;
      }
    },
    
    // 检查通知状态
    checkNotifyStatus() {
      if (!this.connectedDevice) {
        console.log('设备未连接，无需检查通知状态');
        return;
      }
      
      const now = Date.now();
      // 如果超过10秒没有收到数据，重新启用通知
      if (now - this.lastReceiveTime > 10000) {
        console.log('超过10秒未收到数据，重新启用通知');
        this.reEnableNotify();
      }
    },
    
    // 重新启用通知
    reEnableNotify() {
      if (!this.connectedDevice) return;
      
      console.log('重新启用通知');
      // 重新启用 FFF0 服务的通知
      this.enableNotify(
        this.connectedDevice.deviceId,
        this.services.fff0.uuid,
        this.services.fff0.characteristics.notify
      );
      
      // 重新启用 FFF1 服务的通知
      this.enableNotify(
        this.connectedDevice.deviceId,
        this.services.fff1.uuid,
        this.services.fff1.characteristics.notify
      );
      
      // 重新启用 D0FF 服务的通知
      this.enableNotify(
        this.connectedDevice.deviceId,
        this.services.d0ff.uuid,
        this.services.d0ff.characteristics.notify
      );
    },

    // 添加hexStringToUint8Array函数
    hexStringToUint8Array(hexString) {
      try {
        // 移除可能存在的空格
        hexString = hexString.replace(/\s/g, '');
        
        // 确保字符串长度为偶数
        if (hexString.length % 2 !== 0) {
          console.warn('[ADPCM] 十六进制字符串长度不是偶数');
          hexString = hexString.padStart(hexString.length + 1, '0');
        }
        
        const bytes = new Uint8Array(hexString.length / 2);
        for (let i = 0; i < hexString.length; i += 2) {
          const byte = parseInt(hexString.substr(i, 2), 16);
          if (isNaN(byte)) {
            console.warn('[ADPCM] 无效的十六进制字符:', hexString.substr(i, 2));
            bytes[i / 2] = 0;
          } else {
            bytes[i / 2] = byte;
          }
        }
        return bytes;
      } catch (error) {
        console.error('[ADPCM] hexStringToUint8Array转换失败:', error);
        return new Uint8Array(0);
      }
    },

    // 蓝牙数据接收处理
    async handleBluetoothData(frame) {
      try {
        console.log('[ADPCM] handleBluetoothData 入参:', frame);
        const bytes = typeof frame.value === 'string' ? this.hexStringToUint8Array(frame.value) : frame.value;
        const typeHex = bytes[3].toString(16).padStart(2, '0');
        console.log('[ADPCM] 帧类型:', typeHex, '数据长度:', bytes.length);
        
        // 收到首帧时，重置缓冲区状态
        if (typeHex.toLowerCase() === '00') {
          console.log('[ADPCM] 收到首帧，重置缓冲区状态');
          this.audioBuffer.isStartFrameSent = false;
          this.audioBuffer.isEndFrameSent = false;
          this.audioBuffer.data = new Uint8Array(0);
          this.audioBuffer.lastSendTime = 0;
          
          // 直接处理首帧
          console.log('[WebSocket] 开始处理首帧');
          await this.processStartFrame(frame);
          return;
        }
        
        // 如果是结束帧，直接处理
        if (typeHex.toLowerCase() === '02') {
          console.log('[ADPCM] 收到结束帧，准备发送结束帧');
          // 标记已收到结束帧
          this.resultMergeConfig.isEndFrameReceived = true;
          
          // 先发送剩余的数据
          if (this.audioBuffer.data.length > 0) {
            console.log('[ADPCM] 发送剩余数据');
            await this.sendBufferedData(false);
          }
          
          // 发送结束帧
          if (!this.audioBuffer.isEndFrameSent) {
            console.log('[WebSocket] 发送结束帧');
            const endFrame = {
              type: 'audio',
              frame_type: 2,
              data: ''
            };
            
            await new Promise((resolve, reject) => {
              this.socketTask.send({
                data: JSON.stringify(endFrame),
                success: () => {
                  console.log('[WebSocket] 结束帧发送成功');
                  this.audioBuffer.isEndFrameSent = true;
                  resolve();
                },
                fail: (error) => {
                  console.error('[WebSocket] 结束帧发送失败:', error);
                  reject(error);
                }
              });
            });
          }
          
          this.decodeAndGenWavLocal();
          return;
        }
        
        // 处理其他帧
        const realtimePcmData = this.adpcmDecoder.pushFrame(frame);
        if (realtimePcmData) {
          console.log('[ADPCM] 解码成功，PCM数据长度:', realtimePcmData.length);
          
          // 将PCM数据添加到缓冲区
          const pcmData = new Int16Array(realtimePcmData);
          const newData = new Uint8Array(pcmData.buffer);
          
          // 合并数据
          const combinedData = new Uint8Array(this.audioBuffer.data.length + newData.length);
          combinedData.set(this.audioBuffer.data);
          combinedData.set(newData, this.audioBuffer.data.length);
          this.audioBuffer.data = combinedData;
          
          console.log('[ADPCM] 缓冲区数据信息:', {
            currentLength: this.audioBuffer.data.length,
            minStartFrameSize: this.audioBuffer.minStartFrameSize,
            frameSize: this.audioBuffer.frameSize,
            maxBufferSize: this.audioBuffer.maxBufferSize
          });
          
          // 检查是否需要发送数据
          await this.checkAndSendData();
        }
        
        this.adpcmStatus = this.adpcmDecoder.getStatus();
        this.pcmBlobUrl = this.adpcmDecoder.getPcmBlobUrl();
        console.log('[ADPCM] 当前状态:', this.adpcmStatus);
      } catch (error) {
        console.error('[ADPCM] 处理蓝牙数据异常:', error);
      }
    },

    // 新增检查并发送数据方法
    async checkAndSendData() {
      return new Promise((resolve, reject) => {
        const now = Date.now();
        const timeSinceLastSend = now - this.audioBuffer.lastSendTime;
        
        // 如果还没有发送起始帧，检查数据量是否足够
        if (!this.audioBuffer.isStartFrameSent) {
          if (this.audioBuffer.data.length >= this.audioBuffer.minStartFrameSize) {
            console.log('[ADPCM] 缓冲区数据量达到起始帧要求，开始发送');
            this.sendBufferedData().then(resolve).catch(reject);
          } else {
            console.log('[ADPCM] 等待更多数据，当前长度:', this.audioBuffer.data.length);
            resolve();
          }
          return;
        }
        
        // 如果已经发送了起始帧，检查是否有足够的数据发送中间帧
        if (this.audioBuffer.data.length >= this.audioBuffer.frameSize && 
            timeSinceLastSend >= this.audioBuffer.sendInterval) {
          console.log('[ADPCM] 发送中间帧数据');
          this.sendBufferedData().then(resolve).catch(reject);
        } else {
          resolve();
        }
      });
    },

    // 修改发送缓冲数据方法
    sendBufferedData(isEndFrame = false) {
      return new Promise((resolve, reject) => {
        if (!this.isWsConnected || !this.socketTask) {
          console.log('[WebSocket] 连接未就绪，数据保留在缓冲区');
          reject(new Error('WebSocket未连接'));
          return;
        }
        
        try {
          // 标记开始发送音频数据
          this.heartbeatConfig.isSendingAudio = true;
          
          // 如果还没有发送起始帧，先发送起始帧
          if (!this.audioBuffer.isStartFrameSent) {
            console.log('[WebSocket] 发送起始帧');
            const startFrameSize = Math.min(this.audioBuffer.data.length, this.audioBuffer.minStartFrameSize);
            const startFrameData = this.audioBuffer.data.slice(0, startFrameSize);
            
            console.log('[WebSocket] 起始帧数据信息:', {
              dataLength: startFrameData.length,
              minRequiredSize: this.audioBuffer.minStartFrameSize,
              isEnough: startFrameData.length >= this.audioBuffer.minStartFrameSize
            });
            
            const startFrame = {
              type: 'audio',
              frame_type: 0,
              data: uni.arrayBufferToBase64(startFrameData.buffer)
            };
            
            this.socketTask.send({
              data: JSON.stringify(startFrame),
              success: () => {
                console.log('[WebSocket] 起始帧发送成功');
                this.audioBuffer.isStartFrameSent = true;
                this.audioBuffer.lastSendTime = Date.now();
                // 移除已发送的数据
                this.audioBuffer.data = this.audioBuffer.data.slice(startFrameSize);
                // 继续发送剩余数据
                this.checkAndSendData().then(resolve).catch(reject);
              },
              fail: (error) => {
                console.error('[WebSocket] 起始帧发送失败:', error);
                this.heartbeatConfig.isSendingAudio = false; // 发送失败时重置状态
                reject(error);
              }
            });
            return;
          }
          
          // 发送中间帧或结束帧
          const frameType = isEndFrame ? 2 : 1;
          const chunkSize = Math.min(this.audioBuffer.data.length, this.audioBuffer.frameSize);
          
          // 如果是结束帧且没有数据，发送空数据
          if (isEndFrame && chunkSize === 0) {
            console.log('[WebSocket] 发送空结束帧');
            const endFrame = {
              type: 'audio',
              frame_type: 2,
              data: ''
            };
            
            this.socketTask.send({
              data: JSON.stringify(endFrame),
              success: () => {
                console.log('[WebSocket] 结束帧发送成功');
                this.audioBuffer.isEndFrameSent = true;
                this.audioBuffer.lastSendTime = Date.now();
                this.heartbeatConfig.isSendingAudio = false; // 发送完成后重置状态
                resolve();
              },
              fail: (error) => {
                console.error('[WebSocket] 结束帧发送失败:', error);
                this.heartbeatConfig.isSendingAudio = false; // 发送失败时重置状态
                reject(error);
              }
            });
            return;
          }
          
          // 如果数据量太小且不是结束帧，暂不发送
          if (chunkSize < this.audioBuffer.minChunkSize && !isEndFrame) {
            console.log('[ADPCM] 数据量不足，等待更多数据');
            this.heartbeatConfig.isSendingAudio = false; // 不发送时重置状态
            resolve();
            return;
          }
          
          const chunk = this.audioBuffer.data.slice(0, chunkSize);
          
          console.log('[WebSocket] 发送数据帧:', {
            frame_type: frameType,
            data_length: chunk.length,
            is_end_frame: isEndFrame,
            time_since_last_send: Date.now() - this.audioBuffer.lastSendTime
          });
          
          const frameMessage = {
            type: 'audio',
            frame_type: frameType,
            data: uni.arrayBufferToBase64(chunk.buffer)
          };
          
          this.socketTask.send({
            data: JSON.stringify(frameMessage),
            success: () => {
              console.log('[WebSocket] 数据帧发送成功');
              this.audioBuffer.lastSendTime = Date.now();
              // 移除已发送的数据
              this.audioBuffer.data = this.audioBuffer.data.slice(chunkSize);
              
              if (isEndFrame) {
                this.audioBuffer.isEndFrameSent = true;
                this.heartbeatConfig.isSendingAudio = false; // 发送完成后重置状态
                resolve();
              } else if (this.audioBuffer.data.length > 0) {
                // 如果还有数据且不是结束帧，继续发送
                setTimeout(() => {
                  this.checkAndSendData().then(resolve).catch(reject);
                }, this.audioBuffer.sendInterval);
              } else {
                this.heartbeatConfig.isSendingAudio = false; // 发送完成后重置状态
                resolve();
              }
            },
            fail: (error) => {
              console.error('[WebSocket] 数据帧发送失败:', error);
              this.heartbeatConfig.isSendingAudio = false; // 发送失败时重置状态
              reject(error);
            }
          });
        } catch (error) {
          console.error('[WebSocket] 发送缓冲数据异常:', error);
          this.heartbeatConfig.isSendingAudio = false; // 发生异常时重置状态
          reject(error);
        }
      });
    },

    // 修改处理首帧方法
    async processStartFrame(frame) {
      try {
        console.log('[ADPCM] 开始处理首帧');
        // 清空队列和缓冲区
        this.dataQueueManager.queue = [];
        this.wsRetryCount = 0;
        this.audioBuffer.data = new Uint8Array(0);
        this.audioBuffer.isStartFrameSent = false;
        this.audioBuffer.isEndFrameSent = false;
        this.audioBuffer.lastSendTime = 0;
        
        // 确保WebSocket已连接
        if (!this.isWsConnected || !this.socketTask) {
          console.log('[WebSocket] 连接未就绪，尝试初始化连接');
          try {
            await this.initWebSocket();
          } catch (error) {
            console.error('[WebSocket] 初始化连接失败:', error);
            return;
          }
        }

        // 处理首帧数据
        await this.processStartFrameData(frame);
      } catch (error) {
        console.error('[ADPCM] 处理首帧异常:', error);
      }
    },

    // 修改处理首帧数据方法
    async processStartFrameData(frame) {
      try {
        console.log('[ADPCM] 开始处理首帧数据');
        // 解码当前帧
        const realtimePcmData = this.adpcmDecoder.pushFrame(frame);
        console.log('[ADPCM] 首帧解码结果:', {
          hasData: !!realtimePcmData,
          dataType: realtimePcmData ? realtimePcmData.constructor.name : 'null',
          dataLength: realtimePcmData ? realtimePcmData.length : 0
        });
        
        // 将数据添加到缓冲区
        if (realtimePcmData && realtimePcmData.length > 0) {
          const pcmData = new Int16Array(realtimePcmData);
          this.audioBuffer.data = new Uint8Array(pcmData.buffer);
        } else {
          // 使用静音数据
          const silenceData = new Int16Array(128).fill(0);
          this.audioBuffer.data = new Uint8Array(silenceData.buffer);
        }
        
        // 检查是否需要发送数据
        await this.checkAndSendData();
      } catch (error) {
        console.error('[ADPCM] 处理首帧数据异常:', error);
      }
    },

    // 获取语言列表
    async getLanguages() {
      try {
        const res = await uni.request({
          url: 'http://qixin.yeshan.fun/languages',
          method: 'GET',
          header: {
            'Accept': 'application/json',
            'Content-Type': 'application/json'
          }
        });
        
        if (res.statusCode === 200 && res.data) {
          this.languages = res.data;
          console.log('[WebSocket] 获取语言列表成功:', this.languages);
          return true;
        } else {
          console.error('[WebSocket] 获取语言列表失败:', res);
          return false;
        }
      } catch (error) {
        console.error('[WebSocket] 获取语言列表异常:', error);
        return false;
      }
    },

    // 修改初始化WebSocket方法
    async initWebSocket() {
      if (this.socketTask || this.wsStatus === '正在连接...') {
        console.log('[WebSocket] 已有连接或正在连接中');
        return;
      }
      
      // 如果App在后台，不进行连接
      if (this.wsState.isAppHide) {
        console.log('[WebSocket] App在后台，暂不连接');
        return;
      }
      
      // 清除可能存在的定时器
      this.clearWebSocketTimers();
      
      console.log('[WebSocket] 开始初始化连接');
      this.wsStatus = '正在连接...';
      this.isWsConnected = false;
      this.wsState.isManualClose = false;
      
      try {
        // 创建WebSocket连接
        this.socketTask = uni.connectSocket({
          url: this.wsUrl,
          header: this.wsConfig.header,
          protocols: this.wsConfig.protocols,
          success: () => {
            console.log('[WebSocket] 连接创建成功');
          },
          fail: (error) => {
            console.error('[WebSocket] 连接创建失败:', error);
            this.handleWebSocketError(error);
          }
        });
        
        // 监听WebSocket连接打开
        this.socketTask.onOpen((res) => {
          console.log('[WebSocket] 连接已建立，响应:', res);
          this.wsStatus = '已连接';
          this.isWsConnected = true;
          this.wsState.reconnectCount = 0;
          
          // 启动心跳检测
          this.startHeartbeat();
          
          // 发送所有缓冲的数据
          this.processDataQueue();
        });
        
        // 监听WebSocket错误
        this.socketTask.onError((error) => {
          console.error('[WebSocket] 连接错误:', error);
          this.handleWebSocketError(error);
        });
        
        // 监听WebSocket关闭
        this.socketTask.onClose((res) => {
          this.handleWebSocketClose(res);
        });
        
        // 监听WebSocket消息
        this.socketTask.onMessage((res) => {
          this.handleWebSocketMessage(res);
        });

        // 等待连接建立
        await new Promise((resolve, reject) => {
          const timeout = setTimeout(() => {
            reject(new Error('WebSocket连接超时'));
          }, 5000);

          const checkConnection = () => {
            if (this.isWsConnected) {
              clearTimeout(timeout);
              resolve();
            } else {
              setTimeout(checkConnection, 100);
            }
          };
          checkConnection();
        });

        console.log('[WebSocket] 连接已就绪，可以开始发送数据');
      } catch (error) {
        console.error('[WebSocket] 初始化异常:', error);
        this.handleWebSocketError(error);
        throw error;
      }
    },

    // 修改心跳检测方法
    startHeartbeat() {
      this.clearWebSocketTimers();
      this.heartbeatConfig.isHeartbeatEnabled = true;
      this.heartbeatConfig.lastHeartbeatTime = Date.now();
      
      this.wsHeartbeatTimer = setInterval(() => {
        if (!this.isWsConnected || !this.heartbeatConfig.isHeartbeatEnabled) {
          console.log('[WebSocket] 心跳检测已停止');
          this.clearWebSocketTimers();
          return;
        }

        // 如果正在发送音频数据，跳过心跳
        if (this.heartbeatConfig.isSendingAudio) {
          console.log('[WebSocket] 正在发送音频数据，跳过心跳');
          return;
        }

        const now = Date.now();
        const timeSinceLastHeartbeat = now - this.heartbeatConfig.lastHeartbeatTime;
        
        // 检查是否需要发送心跳
        if (timeSinceLastHeartbeat >= this.heartbeatConfig.interval) {
          try {
            this.socketTask.send({
              data: JSON.stringify({ type: 'heartbeat' }),
              success: () => {
                console.log('[WebSocket] 心跳包发送成功');
                this.heartbeatConfig.lastHeartbeatTime = now;
              },
              fail: (error) => {
                console.error('[WebSocket] 心跳包发送失败:', error);
                this.handleWebSocketError(error);
              }
            });
          } catch (error) {
            console.error('[WebSocket] 心跳包发送异常:', error);
            this.handleWebSocketError(error);
          }
        }
      }, this.heartbeatConfig.interval);
    },

    // 修改清除定时器方法
    clearWebSocketTimers() {
      if (this.wsHeartbeatTimer) {
        clearInterval(this.wsHeartbeatTimer);
        this.wsHeartbeatTimer = null;
      }
      if (this.wsRetryTimer) {
        clearTimeout(this.wsRetryTimer);
        this.wsRetryTimer = null;
      }
      this.heartbeatConfig.isHeartbeatEnabled = false;
    },

    // 修改发送PCM数据方法
    sendPcmData(pcmData) {
      if (!this.isWsConnected || this.wsStatus !== '已连接') {
        console.log('[WebSocket] 连接未就绪，数据存入队列');
        this.addToQueue(pcmData);
        return;
      }

      // 将数据添加到队列
      this.addToQueue(pcmData);
      
      // 检查队列大小，如果达到最小发送数量则开始处理
      if (this.dataQueueManager.queue.length >= this.dataQueueManager.minSendSize && !this.dataQueueManager.isProcessing) {
        this.processDataQueue();
      }
    },

    // 新增队列管理方法
    addToQueue(data) {
      // 检查队列大小限制
      if (this.dataQueueManager.queue.length >= this.dataQueueManager.maxQueueSize) {
        console.warn('[Queue] 队列已满，丢弃最旧的数据');
        this.dataQueueManager.queue.shift(); // 移除最旧的数据
      }
      
      this.dataQueueManager.queue.push(data);
      console.log('[Queue] 数据已添加到队列，当前长度:', this.dataQueueManager.queue.length);
    },

    // 修改队列处理方法
    async processDataQueue() {
      if (this.dataQueueManager.isProcessing) return;
      
      this.dataQueueManager.isProcessing = true;
      
      try {
        // 检查是否需要发送起始帧
        let hasSentStartFrame = false;
        
        while (this.isWsConnected && this.dataQueueManager.queue.length > 0) {
          const data = this.dataQueueManager.queue[0];
          
          try {
            await new Promise((resolve, reject) => {
              // 确保数据是ArrayBuffer格式
              const buffer = data instanceof ArrayBuffer ? data : 
                           data instanceof Uint8Array ? data.buffer :
                           new Uint8Array(data).buffer;
              
              // 将数据转换为Base64
              const base64Data = uni.arrayBufferToBase64(buffer);
              
              // 构建音频帧消息
              const frameMessage = {
                type: 'audio',
                frame_type: !hasSentStartFrame ? 0 : // 第一帧作为起始帧
                          this.dataQueueManager.queue.length === 1 ? 2 : // 最后一帧作为结束帧
                          1, // 其他帧作为中间帧
                data: base64Data
              };
              
              // 如果是起始帧，标记已发送
              if (frameMessage.frame_type === 0) {
                hasSentStartFrame = true;
              }
              
              this.socketTask.send({
                data: JSON.stringify(frameMessage),
                success: () => {
                  console.log('[WebSocket] 数据发送成功，frame_type:', frameMessage.frame_type);
                  this.dataQueueManager.queue.shift();
                  resolve();
                },
                fail: (error) => {
                  console.error('[WebSocket] 数据发送失败:', error);
                  reject(error);
                }
              });
            });
            
            // 控制处理间隔
            const now = Date.now();
            const timeSinceLastProcess = now - this.dataQueueManager.lastProcessTime;
            if (timeSinceLastProcess < this.dataQueueManager.processInterval) {
              await new Promise(resolve => 
                setTimeout(resolve, this.dataQueueManager.processInterval - timeSinceLastProcess)
              );
            }
            this.dataQueueManager.lastProcessTime = Date.now();
            
          } catch (error) {
            console.error('[WebSocket] 发送异常:', error);
            this.handleWebSocketError(error);
            break;
          }
        }
      } finally {
        this.dataQueueManager.isProcessing = false;
      }
    },

    // 修改关闭WebSocket方法
    closeWebSocket() {
      // 如果还有未发送的数据，先发送结束帧
      if (this.audioBuffer.data.length > 0 || !this.audioBuffer.isEndFrameSent) {
        console.log('[WebSocket] 发送结束帧并等待结果');
        this.sendBufferedData(true).then(() => {
          // 等待一段时间确保结束帧被处理
          setTimeout(() => {
            this.doCloseWebSocket();
          }, 1000);
        }).catch(error => {
          console.error('[WebSocket] 发送结束帧失败:', error);
          this.doCloseWebSocket();
        });
      } else {
        this.doCloseWebSocket();
      }
    },

    // 新增实际关闭WebSocket的方法
    doCloseWebSocket() {
      this.wsState.isManualClose = true;
      this.clearWebSocketTimers();
      
      if (this.wsState.reconnectTimer) {
        clearTimeout(this.wsState.reconnectTimer);
        this.wsState.reconnectTimer = null;
      }
      
      if (this.socketTask) {
        try {
          this.socketTask.close({
            success: () => {
              console.log('[WebSocket] 连接关闭成功');
            },
            fail: (error) => {
              console.error('[WebSocket] 连接关闭失败:', error);
            }
          });
        } catch (error) {
          console.error('[WebSocket] 关闭连接异常:', error);
        }
        this.socketTask = null;
      }
      
      this.wsStatus = '未连接';
      this.isWsConnected = false;
      this.heartbeatConfig.isHeartbeatEnabled = false;
      
      // 清空队列
      this.dataQueueManager.queue = [];
      this.dataQueueManager.isProcessing = false;
    },

    // 修改错误处理方法
    handleWebSocketError(error) {
      console.error('[WebSocket] 错误处理:', error);
      this.wsStatus = '连接错误';
      this.isWsConnected = false;
      
      // 清除定时器
      this.clearWebSocketTimers();
      
      // 如果是403错误，尝试使用备用连接
      if (error.errMsg && error.errMsg.includes('403')) {
        console.error('[WebSocket] 403 Forbidden错误，尝试备用连接');
        this.tryAlternativeConnection();
        return;
      }
      
      // 如果不是手动关闭且App不在后台，则尝试重连
      if (!this.wsState.isManualClose && !this.wsState.isAppHide) {
        this.scheduleReconnect();
      }
    },

    // 修改备用连接方法
    tryAlternativeConnection() {
      console.log('[WebSocket] 尝试备用连接方式');
      
      // 尝试使用不同的协议和配置
      const alternativeConfig = {
        ...this.wsConfig,
        header: {
          ...this.wsConfig.header,
          'Origin': 'http://localhost:8080'
        },
        protocols: ['speech-protocol-v2']
      };
      
      // 尝试使用不同的URL格式
      const alternativeUrl = this.wsUrl.replace('ws://', 'wss://');
      
      console.log('[WebSocket] 尝试备用连接:', {
        url: alternativeUrl,
        config: alternativeConfig
      });
      
      this.socketTask = uni.connectSocket({
        url: alternativeUrl,
        header: alternativeConfig.header,
        protocols: alternativeConfig.protocols,
        success: () => {
          console.log('[WebSocket] 备用连接创建成功');
        },
        fail: (error) => {
          console.error('[WebSocket] 备用连接创建失败:', error);
          this.wsStatus = '连接失败';
          this.isWsConnected = false;
        }
      });
    },

    // 新增重连调度方法
    scheduleReconnect() {
      if (this.wsState.reconnectTimer) {
        clearTimeout(this.wsState.reconnectTimer);
      }
      
      if (this.wsState.reconnectCount < this.wsState.maxReconnectCount) {
        this.wsState.reconnectCount++;
        console.log('[WebSocket] 尝试重新连接，第', this.wsState.reconnectCount, '次');
        
        this.wsState.reconnectTimer = setTimeout(() => {
          this.initWebSocket();
        }, this.wsState.reconnectInterval * this.wsState.reconnectCount);
      } else {
        console.log('[WebSocket] 达到最大重试次数，尝试备用连接');
        this.tryAlternativeConnection();
      }
    },

    // 修改WebSocket关闭处理方法
    handleWebSocketClose(res) {
      console.log('[WebSocket] 连接已关闭:', res);
      this.wsStatus = '已关闭';
      this.isWsConnected = false;
      this.socketTask = null;
      
      // 清除心跳定时器
      this.clearWebSocketTimers();
      
      // 如果不是手动关闭且App不在后台，则尝试重连
      if (!this.wsState.isManualClose && !this.wsState.isAppHide) {
        this.scheduleReconnect();
      }
    },

    // 修改decodeAndGenWavLocal方法，移除WebSocket发送逻辑
    decodeAndGenWavLocal() {
      try {
        console.log('[ADPCM] decodeAndGenWavLocal 调用');
        // 打印当前平台信息
        let platform = '';
        if (typeof uni !== 'undefined' && uni.getSystemInfoSync) {
          const sysInfo = uni.getSystemInfoSync();
          platform = sysInfo.platform;
          console.log('[ADPCM] 当前uni平台:', platform, sysInfo);
        }
        if (typeof plus !== 'undefined' && plus.os && plus.os.name) {
          console.log('[ADPCM] 当前plus平台:', plus.os.name);
        }
        const adpcm = new Uint8Array(this.adpcmDecoder.adpcmBuffer);
        console.log('[ADPCM] decodeAndGenWavLocal, adpcm.length=', adpcm.length);
        console.log('[ADPCM] 原始ADPCM数据(前100字节):', Array.from(adpcm.slice(0, 100)));

        // ====== 首帧头部解析（参考C语言） ======
        if (adpcm.length < 4) {
          console.error('[ADPCM] ADPCM数据太短，无法解析首帧头部');
          return;
        }
        // 2字节预测值（小端），1字节stepIndex，1字节保留/未用
        const pred = adpcm[0] | (adpcm[1] << 8);
        const stepIdx = adpcm[2];
        // const reserved = adpcm[3]; // 可忽略
        const adpcmData = adpcm.slice(4);
        console.log('[ADPCM] 解析首帧头部: pred=', pred, 'stepIdx=', stepIdx, 'adpcmData.length=', adpcmData.length);

        // 调用解码器，传入初始状态
        if (typeof imaAdpcmDecode === 'undefined') {
          console.error('[ADPCM] imaAdpcmDecode函数未定义');
          return;
        }
        
        // 验证输入数据
        if (!adpcmData || adpcmData.length === 0) {
          console.error('[ADPCM] ADPCM数据为空');
          return;
        }
        
        console.log('[ADPCM] 开始解码，输入数据长度:', adpcmData.length);
        const pcm = imaAdpcmDecode(adpcmData, { 
          last: pred, 
          stepIndex: stepIdx 
        });
        
        if (!pcm || pcm.length === 0) {
          console.error('[ADPCM] 解码失败，未生成PCM数据');
          return;
        }
        
        console.log('[ADPCM] decodeAndGenWavLocal, pcm.length=', pcm.length);
        console.log('[ADPCM] PCM数据(前10个样本):', Array.from(pcm.slice(0, 10)));

        if (typeof pcmToWav === 'undefined') {
          console.error('[ADPCM] pcmToWav函数未定义');
          return;
        }
        
        const wavBuffer = pcmToWav(pcm, 8000);
        if (!wavBuffer) {
          console.error('[ADPCM] 生成WAV数据失败');
          return;
        }
        
        const wavView = new Uint8Array(wavBuffer);
        console.log('[ADPCM] 写入文件的WAV数据(前100字节):', Array.from(wavView.slice(0, 100)), '总长度:', wavView.length);

        // #ifdef APP-PLUS
        console.log('[ADPCM] 进入APP-PLUS分支，base64方式上传');
        const wavData = new Uint8Array(wavBuffer);
        const base64 = uni.arrayBufferToBase64(wavData);

        // 生成带详细时间戳的文件名
        const now = new Date();
        const timestamp = now.getFullYear() + 
                         ('0' + (now.getMonth() + 1)).slice(-2) + 
                         ('0' + now.getDate()).slice(-2) + '_' + 
                         ('0' + now.getHours()).slice(-2) + 
                         ('0' + now.getMinutes()).slice(-2) + 
                         ('0' + now.getSeconds()).slice(-2) + 
                         ('00' + now.getMilliseconds()).slice(-3);
        const filename = `adpcm_${timestamp}.wav`;

        uni.request({
          url: 'http://qixin.yeshan.fun/upload',
          method: 'POST',
          header: {
            'Content-Type': 'application/json'
          },
          data: {
            filename: filename,
            content_base64: base64
          },
          success: (res) => {
            console.log('[ADPCM] 文件上传成功:', res);
            try {
              const data = typeof res.data === 'string' ? JSON.parse(res.data) : res.data;
              if (data.code === 0 && data.data && data.data.url) {
                this.pcmBlobUrl = data.data.url;
                this.adpcmStatus = '解码完成，可播放';
              } else {
                this.pcmBlobUrl = '';
                this.adpcmStatus = '上传失败';
              }
            } catch (e) {
              this.pcmBlobUrl = '';
              this.adpcmStatus = '上传失败';
            }
            this.$forceUpdate();
          },
          fail: (err) => {
            console.error('[ADPCM] 文件上传失败:', err);
            this.adpcmStatus = '上传失败';
            this.$forceUpdate();
          }
        });
        // #endif

        // #ifdef H5
        console.log('[ADPCM] 进入H5分支，准备生成Blob');
        const wavBlob = new Blob([wavBuffer], { type: 'audio/wav' });
        if (this.pcmBlobUrl) {
          URL.revokeObjectURL(this.pcmBlobUrl);
        }
        this.pcmBlobUrl = URL.createObjectURL(wavBlob);
        this.adpcmStatus = '解码完成，可播放';
        console.log('[ADPCM] 解码完成，可播放, pcmBlobUrl:', this.pcmBlobUrl);
        this.$forceUpdate();
        // #endif
      } catch (e) {
        console.error('[ADPCM] decodeAndGenWavLocal 异常:', e);
      }
    },

    // 在device.vue中添加音频播放测试
    playAudio() {
      const audio = new plus.audio.AudioPlayer();
      audio.src = this.pcmBlobUrl;
      audio.play();
    },

    // 修改测试函数
    async testAudioData() {
      try {
        console.log('[Test] 开始音频数据测试');
        
        // 确保WebSocket已连接
        if (!this.isWsConnected) {
          console.log('[Test] WebSocket未连接，初始化连接');
          await this.initWebSocket();
        }
        
        // 使用最后上传的音频文件
        if (!this.pcmBlobUrl) {
          throw new Error('没有可用的音频文件，请先录制或上传音频');
        }
        
        console.log('[Test] 开始获取音频数据:', this.pcmBlobUrl);
        
        // 获取音频数据
        const audioData = await new Promise((resolve, reject) => {
          // #ifdef H5
          fetch(this.pcmBlobUrl)
            .then(response => {
              if (!response.ok) {
                throw new Error('下载失败，状态码：' + response.status);
              }
              return response.arrayBuffer();
            })
            .then(buffer => {
              console.log('[Test] 文件获取成功，数据长度:', buffer.byteLength);
              resolve(buffer);
            })
            .catch(error => {
              console.error('[Test] 文件获取失败:', error);
              reject(error);
            });
          // #endif
          
          // #ifdef APP-PLUS
          uni.request({
            url: this.pcmBlobUrl,
            method: 'GET',
            responseType: 'arraybuffer',
            success: (res) => {
              if (res.statusCode === 200) {
                console.log('[Test] 音频数据获取成功，数据长度:', res.data.byteLength);
                resolve(res.data);
              } else {
                reject(new Error('获取失败，状态码：' + res.statusCode));
              }
            },
            fail: (error) => {
              console.error('[Test] 音频数据获取失败:', error);
              reject(error);
            }
          });
          // #endif
        });
        
        // 确保数据是ArrayBuffer格式
        const pcmData = audioData instanceof ArrayBuffer ? new Uint8Array(audioData) : audioData;
        
        // 检查数据长度
        if (pcmData.length === 0) {
          throw new Error('音频文件为空');
        }
        
        console.log('[Test] PCM数据信息:', {
          dataLength: pcmData.length,
          sampleRate: '8kHz',
          bitsPerSample: 16,
          channels: 1,
          source: this.pcmBlobUrl
        });
        
        // 转换为Base64
        const base64Data = uni.arrayBufferToBase64(pcmData.buffer);
        
        // 发送起始帧
        const startFrame = {
          type: 'audio',
          frame_type: 0,
          data: base64Data
        };
        
        console.log('[Test] 发送起始帧');
        await new Promise((resolve, reject) => {
          this.socketTask.send({
            data: JSON.stringify(startFrame),
            success: () => {
              console.log('[Test] 起始帧发送成功');
              resolve();
            },
            fail: (error) => {
              console.error('[Test] 起始帧发送失败:', error);
              reject(error);
            }
          });
        });
        
        // 发送中间帧
        const middleFrame = {
          type: 'audio',
          frame_type: 1,
          data: base64Data
        };
        
        console.log('[Test] 发送中间帧');
        await new Promise((resolve, reject) => {
          this.socketTask.send({
            data: JSON.stringify(middleFrame),
            success: () => {
              console.log('[Test] 中间帧发送成功');
              resolve();
            },
            fail: (error) => {
              console.error('[Test] 中间帧发送失败:', error);
              reject(error);
            }
          });
        });
        
        // 发送结束帧
        const endFrame = {
          type: 'audio',
          frame_type: 2,
          data: base64Data
        };
        
        console.log('[Test] 发送结束帧');
        await new Promise((resolve, reject) => {
          this.socketTask.send({
            data: JSON.stringify(endFrame),
            success: () => {
              console.log('[Test] 结束帧发送成功');
              resolve();
            },
            fail: (error) => {
              console.error('[Test] 结束帧发送失败:', error);
              reject(error);
            }
          });
        });
        
        console.log('[Test] 测试数据发送完成，等待识别结果...');
        
        // 等待识别结果（最多等待10秒）
        let resultReceived = false;
        const startTime = Date.now();
        
        while (!resultReceived && Date.now() - startTime < 10000) {
          if (this.wsResult) {
            console.log('[Test] 收到识别结果:', {
              recognizedText: this.wsResult,
              timestamp: new Date().toISOString(),
              source: this.pcmBlobUrl
            });
            resultReceived = true;
          }
          await new Promise(resolve => setTimeout(resolve, 100));
        }
        
        if (!resultReceived) {
          console.log('[Test] 未收到识别结果');
        }
        
      } catch (error) {
        console.error('[Test] 测试过程发生错误:', error);
        uni.showToast({
          title: '测试失败：' + error.message,
          icon: 'none'
        });
      }
    },

    // 修改WebSocket消息处理方法
    handleWebSocketMessage(res) {
      console.log('[WebSocket] 收到消息:', res);
      try {
        const data = JSON.parse(res.data);
        if (data.type === 'pong') {
          console.log('[WebSocket] 收到心跳响应');
        } else if (data.type === 'result' && data.text) {
          console.log('[WebSocket] 收到识别结果:', {
            type: data.type,
            text: data.text,
            timestamp: new Date().toISOString(),
            isEndFrameReceived: this.resultMergeConfig.isEndFrameReceived
          });
          
          // 将新结果添加到数组
          this.recognitionResults.push(data.text);
          
          // 更新显示结果
          this.updateTemporaryResult();
          
          // 如果已经收到结束帧，且距离上次合并超过间隔时间，则进行合并
          if (this.resultMergeConfig.isEndFrameReceived) {
            const now = Date.now();
            if (now - this.resultMergeConfig.lastMergeTime >= this.resultMergeConfig.interval) {
              // 清除之前的定时器
              if (this.resultMergeTimer) {
                clearTimeout(this.resultMergeTimer);
              }
              
              // 设置新的定时器来合并结果
              this.resultMergeTimer = setTimeout(() => {
                this.mergeRecognitionResults();
              }, this.resultMergeConfig.interval);
            }
          }
        } else {
          console.log('[WebSocket] 收到其他类型消息:', data);
        }
      } catch (error) {
        console.error('[WebSocket] 解析消息失败:', error, '原始数据:', res.data);
      }
    },
    
    // 修改临时结果更新方法
    updateTemporaryResult() {
      if (this.recognitionResults.length === 0) return;
      
      // 更新临时显示结果
      const tempText = this.recognitionResults.join('');
      console.log('[WebSocket] 更新临时结果:', {
        currentResults: this.recognitionResults,
        tempText: tempText,
        isEndFrameReceived: this.resultMergeConfig.isEndFrameReceived
      });
      
      // 更新显示结果
      this.wsResult = tempText;
    },
    
    // 修改结果合并方法
    mergeRecognitionResults() {
      if (this.recognitionResults.length === 0) return;
      
      // 合并所有结果
      const mergedText = this.recognitionResults.join('');
      console.log('[WebSocket] 合并最终识别结果:', {
        originalResults: this.recognitionResults,
        mergedText: mergedText,
        isEndFrameReceived: this.resultMergeConfig.isEndFrameReceived
      });
      
      // 更新显示结果
      this.wsResult = mergedText;
      
      // 更新最后合并时间
      this.resultMergeConfig.lastMergeTime = Date.now();
      
      // 只有在确认是最终结果时才清空数组
      if (this.resultMergeConfig.isEndFrameReceived) {
        // 清空结果数组
        this.recognitionResults = [];
        
        // 重置结束帧状态
        this.resultMergeConfig.isEndFrameReceived = false;
      }
      
      // 清除定时器
      if (this.resultMergeTimer) {
        clearTimeout(this.resultMergeTimer);
        this.resultMergeTimer = null;
      }
    },
  }
}
</script>

<style>
.device-container {
  padding: 20rpx;
}

.header {
  margin-bottom: 30rpx;
}

.title {
  font-size: 36rpx;
  font-weight: bold;
}

.bluetooth-status {
  background-color: #f5f5f5;
  padding: 20rpx;
  border-radius: 10rpx;
  margin-bottom: 30rpx;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.enable-btn {
  background-color: #007AFF;
  color: white;
  font-size: 28rpx;
  padding: 10rpx 30rpx;
  border-radius: 30rpx;
}

.device-list {
  background-color: #f5f5f5;
  padding: 20rpx;
  border-radius: 10rpx;
}

.list-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20rpx;
}

.scan-btn {
  background-color: #007AFF;
  color: white;
  font-size: 28rpx;
  padding: 10rpx 30rpx;
  border-radius: 30rpx;
}

.no-devices {
  text-align: center;
  padding: 40rpx 0;
  color: #999;
}

.device-items {
  max-height: 600rpx;
  overflow-y: auto;
}

.device-item {
  background-color: white;
  padding: 20rpx;
  margin-bottom: 20rpx;
  border-radius: 10rpx;
}

.device-name {
  font-size: 32rpx;
  font-weight: bold;
  margin-bottom: 10rpx;
  display: block;
}

.device-id {
  font-size: 24rpx;
  color: #666;
  margin-bottom: 10rpx;
  display: block;
}

.device-rssi {
  font-size: 24rpx;
  color: #999;
  display: block;
}

.connected-device {
  margin-top: 30rpx;
  background-color: #f5f5f5;
  padding: 20rpx;
  border-radius: 10rpx;
}

.section-title {
  font-size: 32rpx;
  font-weight: bold;
  margin-bottom: 20rpx;
  display: block;
}

.device-info {
  background-color: white;
  padding: 20rpx;
  border-radius: 10rpx;
}

.disconnect-btn {
  margin-top: 20rpx;
  background-color: #FF3B30;
  color: white;
  font-size: 28rpx;
  padding: 10rpx 30rpx;
  border-radius: 30rpx;
}

.websocket-status {
  margin-top: 30rpx;
  background-color: #f5f5f5;
  padding: 20rpx;
  border-radius: 10rpx;
}

.status-info {
  display: flex;
  align-items: center;
  margin-bottom: 10rpx;
}

.status-text {
  font-size: 28rpx;
  color: #333;
  margin-right: 10rpx;
}

.status-connected {
  color: #4CD964;
  font-size: 32rpx;
  margin-left: 10rpx;
}

.status-connecting {
  color: #FF9500;
  font-size: 32rpx;
  margin-left: 10rpx;
  animation: blink 1s infinite;
}

.status-disconnected {
  color: #FF3B30;
  font-size: 32rpx;
  margin-left: 10rpx;
}

.status-buttons {
  display: flex;
  justify-content: flex-end;
}

@keyframes blink {
  0% { opacity: 1; }
  50% { opacity: 0.5; }
  100% { opacity: 1; }
}

.connect-btn {
  background-color: #007AFF;
  color: white;
  font-size: 28rpx;
  padding: 10rpx 30rpx;
  border-radius: 30rpx;
  margin-left: 20rpx;
}

.disconnect-btn {
  background-color: #FF3B30;
  color: white;
  font-size: 28rpx;
  padding: 10rpx 30rpx;
  border-radius: 30rpx;
  margin-left: 20rpx;
}

.websocket-result {
  margin-top: 20rpx;
  background-color: #f5f5f5;
  padding: 20rpx;
  border-radius: 10rpx;
}

.result-title {
  font-size: 32rpx;
  font-weight: bold;
  margin-bottom: 10rpx;
  display: block;
}

.result-content {
  font-size: 28rpx;
  color: #333;
  white-space: pre-wrap;
  word-break: break-all;
}

.test-btn {
  background-color: #007AFF;
  color: white;
  font-size: 28rpx;
  padding: 10rpx 30rpx;
  border-radius: 30rpx;
  margin-top: 20rpx;
}
</style> 